/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.metadata.rtcustomization.servermanager;

import com.inspur.edp.lcm.metadata.api.entity.*;
import com.inspur.edp.lcm.metadata.common.MetadataDtoConverter;
import com.inspur.edp.lcm.metadata.common.MetadataSerializer;
import com.inspur.edp.lcm.metadata.common.SerializerUtils;
import com.inspur.edp.lcm.metadata.common.ServiceUtils;
import com.inspur.edp.metadata.rtcustomization.api.AbstractCustomizedContent;
import com.inspur.edp.metadata.rtcustomization.api.entity.*;
import com.inspur.edp.metadata.rtcustomization.api.exception.ErrorCodes;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmMetadataCustomizationException;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmMetadataDeployException;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmParseException;
import com.inspur.edp.metadata.rtcustomization.inner.api.ConfigDataService;
import com.inspur.edp.metadata.rtcustomization.inner.api.utils.ConfigDataUtils;
import com.inspur.edp.metadata.rtcustomization.serverapi.CustomizationRtServerService;
import com.inspur.edp.metadata.rtcustomization.serverapi.CustomizationServerService;
import com.inspur.edp.metadata.rtcustomization.serverapi.MetadataDeployService;
import com.inspur.edp.metadata.rtcustomization.serverapi.MetadataFileService;
import com.inspur.edp.metadata.rtcustomization.servermanager.deploymanager.MdRtCustomizationDeployManager;
import com.inspur.edp.metadata.rtcustomization.servermanager.deploymanager.MdRtGeneratedDeployManager;
import com.inspur.edp.metadata.rtcustomization.servermanager.entity.MetadataSyncInfo;
import com.inspur.edp.metadata.rtcustomization.servermanager.event.MetadataDeployEventBroker;
import com.inspur.edp.metadata.rtcustomization.servermanager.utils.MetadataDeployUtils;
import com.inspur.edp.metadata.rtcustomization.servermanager.utils.MetadataStorageUtils;
import com.inspur.edp.metadata.rtcustomization.spi.CustomizationExtHandler;
import com.inspur.edp.metadata.rtcustomization.spi.args.Compare4SameLevelArgs;
import com.inspur.edp.metadata.rtcustomization.spi.event.MdPkgDeployedEventArgs;
import io.iec.edp.caf.commons.transaction.JpaTransaction;
import io.iec.edp.caf.commons.utils.CollectionUtils;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.tenancy.api.ITenantService;
import io.iec.edp.caf.tenancy.api.context.MultiTenantContextInfo;
import io.iec.edp.caf.tenancy.api.entity.AppInstanceInfo;
import io.iec.edp.caf.tenancy.api.entity.Tenant;
import io.iec.edp.caf.tenancy.core.context.MultiTenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.hibernate.persister.entity.PersistersContext;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class MetadataDeployServiceImpl implements MetadataDeployService {
    String language = "zh-CHS";
    String lcmSU = "Lcm";
    String metadataFolder = "metadata";
    private String metadataPath;
    private String targetPath;
    private boolean isMaster;
    private boolean isSync;
    private boolean isPatchAssembly;
    private boolean isSetup;

    List<GspMetadata> customMetadataList = new ArrayList<>();
    List<GspMetadata> generatedMetadataList = new ArrayList<>();
    List<GspMdExtRelation> extRelations = new ArrayList<>();
    List<GspMdChangeset> changeSets = new ArrayList<>();

    private CustomizationRtServerService rtServerService;
    private CustomizationServerService serverService;
    private MetadataFileService metadataFileService;

    @Override
    public void deployMetadata(String metadataPath) {
        rtServerService = SpringBeanUtils.getBean(CustomizationRtServerService.class);
        serverService = SpringBeanUtils.getBean(CustomizationServerService.class);
        this.metadataPath = metadataPath;
        this.isSync = true;
        // 获取需要部署的元数据包信息
        Map<String, MetadataPackage> packageMap = rtServerService.getMetadataPackagesRecursivly(metadataPath);
        if(CollectionUtils.isEmpty(packageMap)){
            log.info("部署完成");
            return;
        }

        JpaTransaction tran = JpaTransaction.getTransaction();
        try{
            tran.begin();
            //部署元数据包
            log.info("正在部署元数据包");
            deployMetadataPackage(packageMap);
            log.info("部署元数据包完成");
            tran.commit();
        }
        catch (Throwable e) {
            try {
                tran.rollback();
            } catch (Exception ex) {
                log.error("deployMetadata rollback error", ex);
            }
            throw e;
        }

        for (MetadataPackage metadataPackage : packageMap.values()) {
            rtServerService.afterMdpkgChanged(metadataPackage);
        }
    }
    
    @Override
    public void deploy(String metadataPath, String targetPath, boolean isMaster, boolean isSync, boolean isPatchAssembly, boolean isSetup) {
        rtServerService = SpringBeanUtils.getBean(CustomizationRtServerService.class);
        serverService = SpringBeanUtils.getBean(CustomizationServerService.class);
        this.metadataPath = metadataPath;
        this.targetPath = targetPath;
        this.isMaster = isMaster;
        this.isSync = isSync;
        this.isPatchAssembly = isPatchAssembly;
        this.isSetup = isSetup;
        //添加清除缓存处理，批量更新补丁时，运行时定制同步获取元数据，如果缓存不清理，会出现获取元数据内容为更新补丁前内容的情况
        serverService.clearAllCache();
        // 获取需要部署的元数据包信息
        Map<String, MetadataPackage> packageMap = rtServerService.getMetadataPackagesRecursivly(metadataPath);
        if(CollectionUtils.isEmpty(packageMap)){
            log.info("部署完成");
            return;
        }

        bakMetadataPackage(packageMap);

//        JpaTransaction tran = JpaTransaction.getTransaction();
        try {
//            tran.begin();
            log.info("开始部署");
            if (isMaster) {
                // 分租户
                ITenantService tenantService = SpringBeanUtils.getBean(ITenantService.class);
                List<Tenant> tenants = SpringBeanUtils.getBean(ITenantService.class).getAllTenants(language);
                for (Tenant tenant : tenants) {
                    List<AppInstanceInfo> appInstanceInfos = tenantService.getAllAppInstInfos(tenant.getId());
                    for (AppInstanceInfo instanceInfo : appInstanceInfos) {
                        //设置当前SU上下文
                        setSUContext(tenant, instanceInfo);
                        JpaTransaction tran = JpaTransaction.getTransaction();
                        try{
                            tran.begin();
                            deploy(packageMap);
                            tran.commit();
                        }
                        catch (Throwable e){
                            try {
                                tran.rollback();
                            } catch (Exception ex) {
                                log.error("deploy rollback error", ex);
                            }
                            throw e;
                        }
                    }
                }
            } else {
                setPersistenceContext();
                JpaTransaction tran = JpaTransaction.getTransaction();
                try{
                    tran.begin();
                    deploy(packageMap);
                    tran.commit();
                }
                catch (Throwable e){
                    try {
                        tran.rollback();
                    } catch (Exception ex) {
                        log.error("deploy rollback error", ex);
                    }
                    throw e;
                }
            }
            // 如果是扩展补丁入库，则入完库需要删除元数据包
            delMdPkg();
//            tran.commit();
            log.info("部署完成");
        } catch (Throwable e) {
//            tran.rollback();
            log.info("部署失败，数据回滚");
            throw new LcmMetadataDeployException(e, ErrorCodes.ECP_METADATA_DEPLOY_0004);
        } finally {
            MultiTenantContextHolder.set(null);
        }
    }

    public void deployMetadataFile(String metadataPath, String targetPath) {
        rtServerService = SpringBeanUtils.getBean(CustomizationRtServerService.class);
        serverService = SpringBeanUtils.getBean(CustomizationServerService.class);
        metadataFileService = SpringBeanUtils.getBean(MetadataFileService.class);
        this.metadataPath = metadataPath;
        this.targetPath = targetPath;

        // 获取需要部署的元数据文件
        Map<File, String> metadataFiles = listMetadataFiles(new File(metadataPath));
        if(CollectionUtils.isEmpty(metadataFiles)){
            log.info("部署完成");
            return;
        }

        bakMetadataFiles(metadataFiles);
        doDeployMetadataFile(metadataFiles);
        log.info("部署完成");
    }

    public void makeUnique() {
        // 分租户
        rtServerService = SpringBeanUtils.getBean(CustomizationRtServerService.class);
        ITenantService tenantService = SpringBeanUtils.getBean(ITenantService.class);
        List<Tenant> tenants = SpringBeanUtils.getBean(ITenantService.class).getAllTenants(language);
        for (Tenant tenant : tenants) {
            List<AppInstanceInfo> appInstanceInfos = tenantService.getAllAppInstInfos(tenant.getId());
            for (AppInstanceInfo instanceInfo : appInstanceInfos) {
                //设置当前SU上下文
                setSUContext(tenant, instanceInfo);
                JpaTransaction tran = JpaTransaction.getTransaction();
                try{
                    tran.begin();
                    rtServerService.makeUnique();
                    tran.commit();
                }
                catch (Throwable e){
                    try {
                        tran.rollback();
                    } catch (Exception ex) {
                        log.error("makeUnique rollback error", ex);
                    }
                    throw e;
                }
            }
        }
    }

    private void setPersistenceContext() {
        PersistersContext.setCurrentLangSuffix("_CHS");
    }

    private void bakMetadataPackage(Map<String, MetadataPackage> packageMap) {
        for (Map.Entry<String, MetadataPackage> packageInfo : packageMap.entrySet()) {
            String relativePath;
            if(metadataPath.length() < metadataFolder.length() + 1){
                relativePath = packageInfo.getKey().substring(metadataPath.length());
            }else{
                relativePath = packageInfo.getKey().substring(metadataPath.length() - metadataFolder.length() - 1);
            }
            String targetPackagePath = Paths.get(targetPath).resolve(relativePath).toString();
            String bakPath = Paths.get(targetPath).resolve("tools/deploy/metadata/bakmdpkgs/").resolve(relativePath).toString();
            String mdPkgName = new File(packageInfo.getKey()).getName();
            String bakMdInPatch = Paths.get(targetPath).resolve("tools/deploy/metadata/bakmdinpatch/").resolve(mdPkgName).toString();
            if(!isPatchAssembly){
                String bakFolderPath = new File(bakMdInPatch).getParent();
                if (!MetadataDeployUtils.getFileService().isDirectoryExist(bakFolderPath)) {
                    MetadataDeployUtils.getFileService().createDirectory(bakFolderPath);
                }
                try {
                    MetadataDeployUtils.getFileService().fileCopy(packageInfo.getKey(), bakMdInPatch);
                } catch (FileSystemException e){
                    log.warn("备份补丁中的元数据包文件时发生文件占用异常",e);
                } catch (IOException e) {
                    log.info("备份元数据包失败：" + packageInfo.getKey());
                    throw new LcmMetadataDeployException(e, ErrorCodes.ECP_METADATA_DEPLOY_0005, packageInfo.getKey());
                }
                continue;
            }
            if (MetadataDeployUtils.getFileService().isFileExist(targetPackagePath)) {
                String bakFolderPath = new File(bakPath).getParent();
                if (!MetadataDeployUtils.getFileService().isDirectoryExist(bakFolderPath)) {
                    MetadataDeployUtils.getFileService().createDirectory(bakFolderPath);
                }
                try {
                    MetadataDeployUtils.getFileService().fileCopy(targetPackagePath, bakPath);
                } catch (FileSystemException e){
                    log.warn("备份补丁中的元数据包文件时发生文件占用异常",e);
                } catch (IOException e) {
                    log.info("备份元数据包失败：" + targetPackagePath);
                }
            }
        }
    }

    private void setSUContext(Tenant tenant, AppInstanceInfo instanceInfo) {
        MultiTenantContextInfo multiTenantContextInfo = new MultiTenantContextInfo();
        multiTenantContextInfo.setTenantId(tenant.getId());
        multiTenantContextInfo.setAppCode(instanceInfo.getCode());
        multiTenantContextInfo.setServiceUnit(lcmSU);
        multiTenantContextInfo.setLanguage(language);
        MultiTenantContextHolder.set(multiTenantContextInfo);
    }

    private void deploy(Map<String, MetadataPackage> packageMap) {
        //部署元数据包
        log.info("正在部署元数据包");
        deployMetadataPackage(packageMap);
        log.info("部署元数据包完成");

        //部署配置数据
        if (isSync) {
            log.info("正在部署运行时定制元数据");
            deployMdData();
            log.info("部署运行时定制元数据完成");
        }
    }

    public void deployMetadataPackage(Map<String, MetadataPackage> packageMap) {
        if (CollectionUtils.isEmpty(packageMap)) {
            return;
        }
        for (String mdpkgPath : packageMap.keySet()) {
            File mdPkgFile = new File(mdpkgPath);
            MetadataPackage metadataPackage = packageMap.get(mdpkgPath);
            MetadataPackageParseResult parseResult = rtServerService.parseMetadataPackage(mdPkgFile, metadataPackage);
            if (parseResult != null && parseResult.isValid()) {
                if (isSync) {
                    try {
                        //部署前检查
                        log.info("部署前检查:{}",mdPkgFile.getAbsolutePath());
                        List<MetadataSyncInfo> syncInfos = saveCheck4Package(parseResult);
                        log.info("部署前检查完成:{}",mdPkgFile.getAbsolutePath());
                        //同步
                        syncMetadata(syncInfos);
                    } finally {
                        MdRtCustomizationDeployManager.getInstance().clearSyncInfo();
                    }
                }

                log.info("解析元数据包:{}", mdPkgFile.getAbsolutePath());
                // 使用预解析的结果
                rtServerService.saveMdpkgWithPreParse(mdPkgFile, isPatchAssembly, parseResult);
                log.info("解析元数据包完成:{}", mdPkgFile.getAbsolutePath());

                if (!isPatchAssembly) {
                    log.info("元数据部署后事件:{}", mdPkgFile.getAbsolutePath());
                    // TODO 梳理每个事件是干什么的
                    fireMdPkgDeployedEvent(packageMap.get(mdpkgPath));
                    log.info("元数据部署后事件完成:{}", mdPkgFile.getAbsolutePath());
                }
            }
        }
    }

    private void fireMdPkgDeployedEvent(MetadataPackage mdPkg) {
        MetadataDeployEventBroker deployEventListener = SpringBeanUtils.getBean(MetadataDeployEventBroker.class);
        MdPkgDeployedEventArgs mdPkgDeployedEventArgs = new MdPkgDeployedEventArgs();
        mdPkgDeployedEventArgs.setPcakage(mdPkg);
        deployEventListener.fireMdPkgDeployedEvent(mdPkgDeployedEventArgs);
    }

    private void delMdPkg() throws IOException {
        if(isSetup){
            return;
        }
        if (isPatchAssembly) {
            File file = new File(metadataPath);
            if (file.exists()) {
                for (File fl : file.listFiles()) {
                    if (fl.isFile()) {
                        FileUtils.forceDelete(fl);
                    }
                    if (fl.isDirectory()) {
                        FileUtils.deleteDirectory(fl);
                    }
                }
            }
        }
    }

    private void deployMdData() {
        //1.获取配置数据
        //2.将配置数据转成元数据识别的实体
        ConfigDataService configDataService = ConfigDataUtils.getConfigDataService();
        if(Objects.isNull(configDataService)){
            return;
        }
        configDataService.handleConfigData(metadataPath, this.customMetadataList,this.generatedMetadataList,this.extRelations,this.changeSets);

        //3SortMetadata
        sortMetadata();

        //扩展关系和元数据一块保存，扩展关系传到部署过程中去
        MdRtCustomizationDeployManager.getInstance().deployCustomizationMdList(customMetadataList, extRelations, changeSets);

        //6.运行时生成元数据保存
        MdRtGeneratedDeployManager.getInstance().saveGeneratedMetadatas(generatedMetadataList);
    }



    private void sortMetadata() {
        if (this.customMetadataList == null || this.customMetadataList.size() <= 0
                || this.extRelations == null || this.extRelations.size() <= 0) {
            return;
        }
        Map<String, GspMetadata> sortedMetadata = new HashMap<>();
        for (GspMetadata metadata : this.customMetadataList) {
            if (!sortedMetadata.containsKey(metadata.getHeader().getId())) {
                List<GspMetadata> dependentMetadatas = new ArrayList<>();
                List<GspMetadata> customMetadatas = new ArrayList<>();

                getDependentMetadataList(metadata.getHeader().getId(), dependentMetadatas);
                if (!CollectionUtils.isEmpty(dependentMetadatas)) {
                    Collections.reverse(dependentMetadatas);
                    dependentMetadatas.forEach(item -> sortedMetadata.put(item.getHeader().getId(), item));
                }
                sortedMetadata.put(metadata.getHeader().getId(), metadata);
                getCustomMetadataList(metadata.getHeader().getId(), customMetadatas);
                if (!CollectionUtils.isEmpty(customMetadatas)) {
                    customMetadatas.forEach(item -> sortedMetadata.put(item.getHeader().getId(), item));
                }
            }
        }
        this.customMetadataList.clear();
        this.customMetadataList.addAll(sortedMetadata.values());
    }

    private void getDependentMetadataList(String metadataId, List<GspMetadata> metadatas) {
        CustomizationServerService service = MetadataDeployUtils.getMetadataServerService();
        GspMdExtRelation relation = this.extRelations.stream().filter(item -> item.getExtMdId().equals(metadataId)).findAny().orElse(null);
        if (relation == null) {
            GspMdExtRelation relation1 = service.getExtRelationByExtMdIdAndCertId(metadataId, null);
            if (relation1 == null) {
                throw new LcmMetadataCustomizationException(ErrorCodes.ECP_METADATA_CUSTOMIZATION_0007, metadataId);
            }
            return;
        }
        GspMetadata metadata = this.customMetadataList.stream().filter(item -> item.getHeader().getId().equals(relation.getBasicMdId())).findAny().orElse(null);
        if (metadata == null) {
            metadata = service.getMetadata(relation.getBasicMdId());
            if (metadata == null) {
                throw new LcmMetadataCustomizationException(ErrorCodes.ECP_METADATA_CUSTOMIZATION_0008, metadataId, relation.getBasicMdId());
            }
            return;
        }
        metadatas.add(metadata);
        getDependentMetadataList(metadata.getHeader().getId(), metadatas);
    }

    private void getCustomMetadataList(String metadataId, List<GspMetadata> metadatas) {
        GspMdExtRelation relation = this.extRelations.stream().filter(item -> item.getBasicMdId().equals(metadataId)).findAny().orElse(null);
        if (relation == null) {
            return;
        }
        GspMetadata metadata = this.customMetadataList.stream().filter(item -> item.getHeader().getId().equals(relation.getExtMdId())).findAny().orElse(null);
        if (metadata == null) {
            return;
        }
        metadatas.add(metadata);
        getDependentMetadataList(metadata.getHeader().getId(), metadatas);
    }

    private List<MetadataSyncInfo> saveCheck4Package(MetadataPackageParseResult parseResult) {
        //clear syncinfos, this position is important
        List<MetadataSyncInfo> syncInfos = new ArrayList<>();

        List<GspMdRtContent> mdpkgMetadataList = parseResult.getRtContentList();

        MetadataPackage metadataPackage = parseResult.getMetadataPackage();
        // 根据元数据包名，获取元数据列表，未获取到，则说明没有，不需要检查冲突
        List<GspMdRtContent> targetMetadataList = rtServerService.getMdRtContentListByMdpkgName(metadataPackage.getHeader().getName());
        if (targetMetadataList.isEmpty() || mdpkgMetadataList.isEmpty()){
            return syncInfos;
        }
        // 将列表转换为 Map 以提高查找效率
        Map<String, GspMdRtContent> mdpkgMetadataMap = mdpkgMetadataList.stream()
                .collect(Collectors.toMap(GspMdRtContent::getMetadataId, content -> content));

        Map<String, GspMdRtContent> targetMetadataMap = targetMetadataList.stream()
                .collect(Collectors.toMap(GspMdRtContent::getMetadataId, content -> content));

        for (GspMetadata metadata : metadataPackage.getMetadataList()) {
            // 使用 Map 替代 filter 查找
            GspMdRtContent oldMdRtContent = targetMetadataMap.get(metadata.getHeader().getId());
            GspMdRtContent newMdRtContent = mdpkgMetadataMap.get(metadata.getHeader().getId());

            //如果目标环境中没有有元数据或者元数据包中没有元数据，不需要检查冲突
            if (oldMdRtContent == null || newMdRtContent == null) {
                continue;
            }
            List<DimensionExtendEntity> extendEntitys = serverService.getMetadataInfoListRecusively(oldMdRtContent.getMetadataId(), oldMdRtContent.getCertId());

                //如果目标环境中有元数据，检查元数据是否被扩展，如果被扩展了，检查冲突
                if (extendEntitys == null || extendEntitys.size() <= 0) {
                    continue;
                } else {
                    String metadataInfoStr = metadata.getHeader().getNameSpace() + "." + metadata.getHeader().getCode() + "." + metadata.getHeader().getType();
                    if (!metadata.getHeader().isExtendable()) {
                        String warningMsg = String.format("警告：元数据不允许扩展，但是存在扩展关系，将按照扩展关系同步内容。请联系产品维护人员，将元数据修改为允许扩展。元数据为：%s", metadataInfoStr);
                        log.info(warningMsg);
                    }
                    log.info("目标环境中存在扩展关系，进行元数据扩展冲突检查，元数据信息：" + metadataInfoStr);
                }

                GspMetadata oldMetadata = rtServerService.getMetadata(oldMdRtContent.getMetadataId());
                String metadataStr = parseResult.getFileContentMap().get(metadata.getRelativePath().substring(1));
                GspMetadata metadataToSync = new MetadataSerializer().deserialize(metadataStr, GspMetadata.class);
                syncInfos.add(new MetadataSyncInfo(metadataToSync, oldMetadata, true, extendEntitys, metadata.getExtendRule()));
                saveCheck4BasicMetadata(metadataToSync, oldMetadata, extendEntitys);
            }

        return syncInfos;
    }

    private void saveCheck4BasicMetadata(GspMetadata sourceMetadta, GspMetadata targetMetadata, List<DimensionExtendEntity> extendEntitys) {
        CustomizationExtHandler manager = MetadataDeployUtils.getCustomizationExtHandler(sourceMetadta.getHeader().getType());
        if (Objects.isNull(manager)) {
            String msg = String.format("未能获取到对应元数据类型的扩展合并处理器，元数据类型：%s", sourceMetadta.getHeader().getType());
            log.info(msg);
        } else {
            AbstractCustomizedContent change = manager.getExtContent4SameLevel(new Compare4SameLevelArgs(sourceMetadta, targetMetadata, sourceMetadta));
            log.info("检查元数据扩展冲突，当前元数据：" + sourceMetadta.getHeader().getNameSpace() + "." + sourceMetadta.getHeader().getCode() + "." + sourceMetadta.getHeader().getType());
            for (DimensionExtendEntity entity : extendEntitys) {
                if (entity.getBasicMetadataId().equals(targetMetadata.getHeader().getId())) {
                    GspMetadata metadata = serverService.getMetadata(entity.getExtendMetadataEntity().getHeader().getId());
                    MdRtCustomizationDeployManager.getInstance().checkConflict(sourceMetadta, metadata, change, extendEntitys, sourceMetadta);
                }
            }
        }
    }

    private void syncMetadata(List<MetadataSyncInfo> syncInfos) {
        log.info("开始同步");
        for (MetadataSyncInfo syncInfo : syncInfos) {
            if (!syncInfo.isNeedSync()) {
                continue;
            }
            CustomizationExtHandler manager = MetadataDeployUtils.getCustomizationExtHandler(syncInfo.getMetadata().getHeader().getType());
            MdRtCustomizationDeployManager.getInstance().syncMetadata(syncInfo.getMetadata(), syncInfo.getDimensionExtendEntityList(), manager, syncInfo.getMetadata());
            MetadataHeader metadataInfo = syncInfo.getMetadata().getHeader();
            log.info("同步元数据" + metadataInfo.getNameSpace() + "." + metadataInfo.getCode() + "." + metadataInfo.getType() + "完成");
        }
        log.info("同步完成");
    }

    private void doDeployMetadataFile(Map<File, String> metadataFileMap) {
        for (File metadataFile : metadataFileMap.keySet()) {
            try {
                String metadataString = MetadataDeployUtils.getFileService().fileRead(metadataFile.getAbsolutePath());
                metadataFileService.save(metadataFile.getName(), metadataFileMap.get(metadataFile), metadataString);
            } catch (IOException e) {
                log.info("部署失败：" + metadataFile.getAbsolutePath());
                throw new LcmMetadataDeployException(e, ErrorCodes.ECP_METADATA_DEPLOY_0004);
            }
        }
    }

    private void bakMetadataFiles(Map<File, String> metadataFiles) {
        // 把文件拷贝到targetPath下的tools/deploy/metadata/bakmetadatafile/文件夹中
        String backupDir = targetPath + File.separator + "tools" + File.separator + "deploy" + File.separator + "metadata" + File.separator + "bakmetadatafile";
        for (File file : metadataFiles.keySet()) {
            if (file.isFile()) {
                Path relativePath = Paths.get(metadataPath).relativize(file.toPath());
                Path destinationPath = Paths.get(backupDir, relativePath.toString());

                try {
                    // 创建目录
                    Files.createDirectories(destinationPath.getParent());
                } catch (IOException e) {
                    log.error("Failed to create parent directories for: " + destinationPath, e);
                    continue; // 继续处理下一个文件
                }

                try {
                    Files.copy(file.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException e) {
                    log.error("Failed to copy file: " + file.getAbsolutePath(), e);
                }
            } else {
                log.error("Skipping non-file: " + file.getAbsolutePath());
            }
        }
    }

    private Map<File, String> listMetadataFiles(File metadataDirFile) {
        Map<File, String> metadataFileMap = new HashMap<>();
        if (metadataDirFile == null || !metadataDirFile.exists()) {
            return metadataFileMap;
        }
        File[] files = metadataDirFile.listFiles();
        if (files == null) {
            return metadataFileMap;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                metadataFileMap.putAll(listMetadataFiles(file));
            } else {
                String relativePath = Paths.get(metadataPath).relativize(file.getParentFile().toPath()).toString();
                metadataFileMap.put(file, relativePath);
            }
        }
        return metadataFileMap;
    }

}
